﻿namespace UnityLog
{
    using System;
    using System.Collections.Generic;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    using UnityEngine;

    public class Log
    {
        private static readonly Log _instance = new Log();
        private System.Action action;
        private List<LogMessage> current;
        private bool interceptOn = true;
        private int messageQueueSize = 0x2004;
        private List<LogMessage> messages;
        private bool useConsole;
        private Dictionary<string, string> watches;

        private Log()
        {
            this.messages = new List<LogMessage>(this.messageQueueSize);
            this.current = new List<LogMessage>();
            this.watches = new Dictionary<string, string>();
        }

        public static void AI(object g, string messages)
        {
        }

        public static void Ani(string message)
        {
            Important(Category.Animation, message);
        }

        public void Clear()
        {
            this.messages.Clear();
        }

        public static void Critical(string message)
        {
            Critical(Category.Console, message);
        }

        public static void Critical(Category category, string message)
        {
            Record(category, Level.Critical, message);
        }

        public int FilterLogs(Category categories, Level level, string keyword, int lockedAt = -1)
        {
            int count;
            <FilterLogs>c__AnonStorey12D storeyd = new <FilterLogs>c__AnonStorey12D {
                categories = categories,
                level = level,
                keyword = keyword
            };
            if (storeyd.keyword == null)
            {
                storeyd.keyword = string.Empty;
            }
            if (lockedAt < 1)
            {
                count = this.messages.Count;
            }
            else
            {
                count = Mathf.Clamp(lockedAt, lockedAt, this.messages.Count);
            }
            this.current = this.messages.GetRange(0, count).FindAll(new Predicate<LogMessage>(storeyd.<>m__1F8));
            this.current.Reverse();
            return this.current.Count;
        }

        public List<LogMessage> GetAllLogs()
        {
            return Instance.messages;
        }

        public Dictionary<string, string> GetAllWatches()
        {
            return this.watches;
        }

        public List<LogMessage> GetRange(int position, int pageSize)
        {
            if (this.current.Count <= pageSize)
            {
                return this.current;
            }
            if (position > (this.current.Count - pageSize))
            {
                position = this.current.Count - pageSize;
            }
            position = Mathf.Max(0, position);
            return this.current.GetRange(position, pageSize);
        }

        public static void GUI(string message)
        {
            Important(Category.GUI, message);
        }

        public static void Important(string message)
        {
            Important(Category.Console, message);
        }

        public static void Important(Category category, string message)
        {
            Record(category, Level.Important, message);
        }

        public bool IsConsoleOn()
        {
            return this.useConsole;
        }

        public bool IsInterceptOn()
        {
            return this.interceptOn;
        }

        public static void Minor(string message)
        {
            Minor(Category.Console, message);
        }

        public static void Minor(Category category, string message)
        {
            Record(category, Level.Minor, message);
        }

        public static void Net(string message)
        {
        }

        public static void Normal(string message)
        {
            Normal(Category.Console, message);
        }

        public static void Normal(Category category, string message)
        {
            Record(category, Level.Normal, message);
        }

        public static void Record(LogMessage logMessage)
        {
            if (Instance.useConsole)
            {
                Debug.Log(logMessage.message);
            }
            else
            {
                if (Instance.messages.Count > 0)
                {
                    LogMessage message = Instance.messages[Instance.messages.Count - 1];
                    string str = logMessage.message + logMessage.stack;
                    string str2 = message.message + message.stack;
                    if (((str == str2) && (message.category == logMessage.category)) && (message.level == logMessage.level))
                    {
                        message.occurances++;
                        if (Instance.action != null)
                        {
                            Instance.action();
                        }
                        return;
                    }
                }
                Instance.messages.Add(logMessage);
                if (Instance.messages.Count > Instance.messageQueueSize)
                {
                    Instance.messages.RemoveAt(0);
                    Instance.action();
                }
            }
        }

        public static void Record(Category category, Level level, string message)
        {
            Record(new LogMessage(Time.time, Time.frameCount, category, level, message, StackTraceUtility.ExtractStackTrace()));
        }

        public static void Record(Category category, Level level, string message, string stack)
        {
            Record(new LogMessage(Time.time, Time.frameCount, category, level, message, stack));
        }

        public void SetConsole(bool redirectToConsole)
        {
            this.useConsole = redirectToConsole;
        }

        public void SetIntercept(bool allowIntercepts)
        {
            this.interceptOn = allowIntercepts;
        }

        public static void SetListener(System.Action action)
        {
            Instance.action = action;
        }

        public static void Sys(string messages)
        {
            Important(Category.System, messages);
        }

        public int TotalLogCount()
        {
            return this.messages.Count;
        }

        public static void Trivial(string message)
        {
            Trivial(Category.Console, message);
        }

        public static void Trivial(Category category, string message)
        {
            Record(category, Level.Trivial, message);
        }

        public static void Watch(string nvpKey, object nvpValue)
        {
            if (nvpValue != null)
            {
                Instance.watches[nvpKey.ToUpper()] = nvpValue.ToString();
            }
            else
            {
                Instance.watches[nvpKey.ToUpper()] = "<null>";
            }
        }

        public int Count
        {
            get
            {
                return this.messages.Count;
            }
        }

        public static Log Instance
        {
            get
            {
                return _instance;
            }
        }

        [CompilerGenerated]
        private sealed class <FilterLogs>c__AnonStorey12D
        {
            internal Log.Category categories;
            internal string keyword;
            internal Log.Level level;

            internal bool <>m__1F8(LogMessage message)
            {
                return ((((this.categories & message.category) > 0) && (message.level >= this.level)) && message.message.ToLower().Contains(this.keyword.ToLower()));
            }
        }

        [Flags]
        public enum Category
        {
            AI = 8,
            Animation = 0x80,
            Camera = 0x200,
            Console = 1,
            General = 0x40,
            GUI = 4,
            Network = 0x10,
            Physics = 0x20,
            Sound = 0x100,
            System = 2
        }

        public enum Level
        {
            Trivial,
            Minor,
            Normal,
            Important,
            Critical
        }

        [Flags]
        public enum Options
        {
            ShowPrefix = 2,
            UseConsole = 1
        }
    }
}

